 package com.lbs.core.shared.parsing;
 
import com.google.gwt.regexp.shared.RegExp;
import com.google.gwt.xml.client.Document;
import com.google.gwt.xml.client.Element;
import com.google.gwt.xml.client.XMLParser;
import com.lbs.core.shared.XmlRawInterface;
import com.lbs.core.shared.tables.AbstractData;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
 
/**
 * Realiza todos los labores de parsing del sistema LizBet.
 * 
 * @author Alberto Sandoval Sotelo Friday 24 August 2012 
 *
 */
 public class LbsParser
 {
   public static Object parse(String string, XmlRawInterface xml, AbstractData data)
     throws LbsParserException
   {
     List<LbsTokenInterface> tokens = new ArrayList<LbsTokenInterface>();
     String[] parts;
     if (string.contains("+"))
       parts = string.split("\\+");
     else {
       parts = new String[] { string };
     }
     String result = "";
     Double numberResult = Double.valueOf(0.0D);
     if ((string == null) || (string.isEmpty())) {
       return "";
     }
     for (String part : parts)
     {
       if (ifTest(part).booleanValue())
         tokens.add(new LbsIfToken(part.trim(), xml, data));
       else if (conditionTest(part).booleanValue())
         tokens.add(new LbsCondition(part.trim(), xml, data));
       else {
         tokens.add(new LbsBasicToken(part.trim(), xml, data));
       }
     }
 
     //Verificamos si todos los elemntos son numericos
     Boolean onlyNumbers = Boolean.valueOf(true);
     if (tokens.size() > 1) {
       for (LbsTokenInterface token : tokens) {
         if (((token.getVal() instanceof String)) || ((token.getVal() instanceof Date)) || ((token.getVal() instanceof Boolean))) {
           onlyNumbers = Boolean.valueOf(false);
           break;
         }
       }
 
     }
 
     if (tokens.size() > 1) {
       for (LbsTokenInterface token : tokens)
         if (onlyNumbers.booleanValue())
           numberResult = Double.valueOf(numberResult + Double.parseDouble(token.getVal().toString()));
         else
           result = result + ((token.getVal() == null) || (token.getVal().equals("null")) ? "" : token.getVal());
       if (onlyNumbers.booleanValue()) {
         return numberResult;
       }
       return result;
     }
     return tokens.get(0).getVal();
   }
 
   public static Boolean test(String string)
   {
     if (string.contains("+"))
       return Boolean.valueOf(true);
     if (string.contains("'"))
       return Boolean.valueOf(true);
     RegExp regExp = RegExp.compile(".*==.* ? .* : .*");
     boolean matchFound = regExp.test(string);
     if (matchFound)
       return Boolean.valueOf(true);
     return Boolean.valueOf(true);
   }
 
   private static Boolean ifTest(String string) {
     Boolean ifMatchFound = Boolean.valueOf(false);
     RegExp ifRegExp = RegExp.compile(".* ? .* : .*");
     ifMatchFound = Boolean.valueOf(ifRegExp.test(string.trim()));
     if (ifMatchFound.booleanValue()) {
       return Boolean.valueOf(true);
     }
     return Boolean.valueOf(false);
   }
 
   private static Boolean conditionTest(String string) {
     Boolean conditionMatchFound = Boolean.valueOf(false);
     RegExp ifEqualRegExp = RegExp.compile(".*==.*");
     RegExp ifLessThanOrEqualRegExp = RegExp.compile(".*<=.*");
     RegExp ifGreaterThanOrEqualRegExp = RegExp.compile(".*>=.*");
     RegExp ifNotEqualRegExp = RegExp.compile(".*!=.*");
     RegExp ifLessThanRegExp = RegExp.compile(".*<.*");
     RegExp ifGreaterThanRegExp = RegExp.compile(".*>.*");
 
     conditionMatchFound = Boolean.valueOf((conditionMatchFound.booleanValue()) || (ifEqualRegExp.test(string.trim())));
     conditionMatchFound = Boolean.valueOf((conditionMatchFound.booleanValue()) || (ifLessThanOrEqualRegExp.test(string.trim())));
     conditionMatchFound = Boolean.valueOf((conditionMatchFound.booleanValue()) || (ifGreaterThanOrEqualRegExp.test(string.trim())));
     conditionMatchFound = Boolean.valueOf((conditionMatchFound.booleanValue()) || (ifNotEqualRegExp.test(string.trim())));
     conditionMatchFound = Boolean.valueOf((conditionMatchFound.booleanValue()) || (ifLessThanRegExp.test(string.trim())));
     conditionMatchFound = Boolean.valueOf((conditionMatchFound.booleanValue()) || (ifGreaterThanRegExp.test(string.trim())));
 
     if (conditionMatchFound.booleanValue()) {
       return Boolean.valueOf(true);
     }
     return Boolean.valueOf(false);
   }
 
   public static List<String> getFields(String string)
   {
     List<LbsTokenInterface> tokens = new ArrayList<LbsTokenInterface>();
     List<String> result = new ArrayList<String>();
     try
     {
       String[] parts;
       if (string.contains("+"))
         parts = string.split("\\+");
       else {
         parts = new String[] { string };
       }
 
       if (string.isEmpty()) {
         return result;
       }
       for (String part : parts)
         if (ifTest(part).booleanValue())
           tokens.add(new LbsIfToken(part.trim(), null, null));
         else if (conditionTest(part).booleanValue())
           tokens.add(new LbsCondition(part.trim(), null, null));
         else
           tokens.add(new LbsBasicToken(part.trim(), null, null));
     }
     catch (LbsParserException e)
     {
       e.printStackTrace();
     }
     for (LbsTokenInterface token : tokens) {
       result.addAll(token.getFields());
     }
 
     List<String> tmp = new ArrayList<String>();
     tmp.addAll(result);
     result.clear();
     for (String s : tmp) {
       if (!result.contains(s)) {
         result.add(s);
       }
     }
 
     return result;
   }
   
   /**
    * Parsea el resultado de un servlet y regresa un AbstractData con los valores regresados por el servidor
    * 
    * @param string El Strin que se va a parsear
    * @return Los valores en forma de AbstractData
    */
   public static AbstractData parseServletResponse(String string){
	    AbstractData result = new AbstractData();
		if (string.startsWith("<pre")){
			Document messageDom = XMLParser.parse(string);
			Element n = (Element) messageDom.getElementsByTagName("pre").item(0);
			result.parse(n.getFirstChild().getNodeValue());
		}else
			result.parse(string);
		
		return result;
   }
 }
